home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’96 / ArrangeScript / Sources / Plugin.cp < prev    next >
Text File  |  1996-06-21  |  14KB  |  436 lines

  1. /*
  2.     This file defines a "generic" plugin module for Arrange 2.0.
  3.     To use it, you should modify the file 'SubClass.h', which subclasses
  4.     the Plugin class definition by adding new fields and private functions,
  5.     and implementing the appropriate methods in another C++ source file.
  6.  
  7.     I'd strongly suggest that you base your plugin on one of the examples,
  8.     or at least be familiar with one or more of them. You should not have to
  9.     examine or make changes to this file or Plugin.h. Most of the code
  10.     contained here hides the details of interfacing Arrange and the module
  11.     'hook' mechanism to C++
  12.  
  13.     There is also a required 'MDdf' resource, which may be built by including
  14.     'Plugin.r' within your own rez source file. Note that the 'MDdf' resource
  15.     built by compiling Plugin.r assumes the 'MDcd' code resource has the same
  16.     'qModuleRsrcID' ID as the MDdf (the usual convention).
  17.  
  18.     This version of Plugin.cp was written by Paul Chambers on 11/27/94 and
  19.     last updated on 12/6/84.
  20.     It is derived from the original GenericPlugin.cp, written by
  21.     Steve Newman on 12/24/93 and last updated on 7/15/94.
  22. */
  23.  
  24. #include "ArrangeCallbacks.h"
  25. #include "PlugIn.h"
  26.  
  27. #include "ArrangeScript.h"
  28.  
  29.  
  30. /*************************************************************************/
  31. /**************************** Main entry point ***************************/
  32. /*************************************************************************/
  33.  
  34. /* Root entry point for the module - must be the first function in the
  35.  * file, so that the linker will place it first in the code segment.
  36.  * This is the routine which Arrange calls at application startup time
  37.  * (and again at quit time).
  38.  * 
  39.  * Most plug-ins will not need to modify this routine or the Hook functions
  40.  * immediately following.  All customization can be done in the "Plugin"
  41.  * section (below).
  42.  */
  43. extern "C" Integer main(ModuleParamBlock *pb, pModuleRootAction action, Integer /*p1*/ ENDP)
  44. {
  45.     ArrangeCallbackTbl* calls;
  46.     Integer                returnValue;
  47.  
  48.     // A4 doesn't yet point to our data segment, so we cannot use any global data.
  49.     SetupGlobals();
  50.  
  51.     /* Extract the callback table from our parameter block, and coerce it
  52.      * to the extended Arrange table.
  53.      */
  54.     calls = (ArrangeCallbackTbl*)(pb->calls);
  55.     
  56.     switch (action)
  57.     {
  58.     case mrLoad:
  59.         // Allocate memory and create a new Plugin object.
  60.         void* storage = calls->mem->AllocMem( sizeof(SubClass),
  61.                                               (AllocMode)(amFreeStore | amErrIfNoMem));
  62.         pb->moduleRefcon = uInteger(new(storage) SubClass(calls));
  63.         returnValue = 1;
  64.         break;
  65.     
  66.     case mrUnload:
  67.         // Dispose of the Plugin object and release the memory it occupies.
  68.         delete (SubClass *)pb->moduleRefcon;
  69.         calls->mem->DeallocMem((void*)pb->moduleRefcon, amFreeStore);
  70.         returnValue = 0;
  71.         break;
  72.     
  73.     case mrFindEntry:
  74.     default:
  75.         // This module contains no extended entry points, so we always return 0 for
  76.         // the mrFindEntry message.  Most plug-ins will not use extended entry points.
  77.         returnValue = 0;
  78.         break;
  79.     
  80.     } // switch (action)
  81.  
  82.     RestoreGlobals();
  83.     return returnValue;
  84. } // OurModuleRoot
  85.  
  86.  
  87. // Stubs to resolve the 'new' & 'delete' references.
  88. void* Plugin::operator new(size_t)
  89. {
  90.     DebugStr("\pError - naked 'operator new' called.");
  91.     return nil;
  92. }
  93.  
  94. /*************************************************************************\
  95.         Class Plugin
  96. \*************************************************************************/
  97.  
  98. /* Construct a Plugin object.  This is called once, from the OurModuleRoot
  99.  * function, when the module is initialized (i.e. at application startup time).
  100.  */
  101. Plugin::Plugin(const ArrangeCallbackTbl* theCalls)
  102. {
  103.     // Record the callback table for future use.
  104.     calls = theCalls;
  105.  
  106. } // Plugin constructor
  107.  
  108.  
  109. /* Dispose of a Plugin object.  This is called when Arrange terminates.  You
  110.  * should free up any data structures which you allocation in the Plugin
  111.  * constructor (above).
  112.  */
  113. Plugin::~Plugin()
  114. {
  115. } // ~Plugin
  116.  
  117.  
  118. /*
  119.     following are a number of groups of routines, which form the bulk
  120.     of the interface between the Arrange module API and the subclass.
  121.  
  122.     The 'moduleRefcon' of the 'ModuleParamBlock' is used to maintain a
  123.     pointer to the subclass derived from this class. The 'InstallxxxxHook'
  124.     routines set up a private 'OurxxxxHook' function, which uses the
  125.     'moduleRefcon' field to establish 'this' and invoke the appropriate
  126.     'xxxxEvent' method, which should be overridden in the subclass.
  127.     The methods provided here are essentially 'do nothing' methods.
  128. */
  129.  
  130. /* This function is called whenever the user clicks in an "interesting place"
  131.  * in a document window.  It should return true if we handle the click, false
  132.  * (the normal case) when the click should be passed along to other plug-ins
  133.  * or to Arrange's normal event processing.  See the documentation for
  134.  * SetClickHook for more details.
  135.  */
  136. void Plugin::InstallClickHook ( uInteger refcon, pBoolean addHook )
  137. {    calls->ui->SetClickHook(OurClickHook, refcon, addHook);    }
  138.  
  139. arHookResult OurClickHook( ModuleParamBlock* pb, arClickLocation loc,
  140.                                     Point where, pShort modifiers, pShort clickCount,
  141.                                     arNoteID note, arFieldID field, arPathID path ENDP )
  142. {
  143.     arHookResult    result;
  144.  
  145.     SetupGlobals();
  146.     result = ((SubClass*)(pb->moduleRefcon))->ClickEvent(
  147.                 loc, where, modifiers, clickCount, note, field, path );
  148.     RestoreGlobals();
  149.     return result;
  150. }
  151. arHookResult Plugin::ClickEvent( arClickLocation /*loc*/, Point /*where*/,
  152.                                              Short /*modifiers*/, Short /*clickCount*/,
  153.                                              arNoteID /*note*/, arFieldID /*field*/,
  154.                                              arPathID /*path*/ )
  155. {
  156.     return false; // Let Arrange handle the event
  157. } // ClickEvent
  158.  
  159.  
  160. /* This function is called whenever the user types a key which matches the
  161.  * filters we pass to SetKeyHook in Plugin's constructor.  It should return
  162.  * true if we handle the event, false (the normal case) when the event
  163.  * should be passed along to other plug-ins or to Arrange's normal event
  164.  * processing.  See the documentation for SetKeyHook for more details.
  165.  */
  166. void Plugin::InstallKeyHook      ( uInteger refcon, pBoolean addHook,
  167.                             pShort charFilter, pShort keyFilter, pShort modFilter )
  168. {
  169.     calls->ui->SetKeyHook  (OurKeyHook, refcon, addHook,
  170.                             charFilter, keyFilter, modFilter);
  171. }
  172.  
  173. arHookResult OurKeyHook( ModuleParamBlock* pb, pShort theChar, pShort key,
  174.                                     pShort modifiers ENDP )
  175. {
  176.     arHookResult    result;
  177.  
  178.     SetupGlobals();
  179.     result = ((SubClass*)(pb->moduleRefcon))->KeyEvent(theChar, key, modifiers);
  180.     RestoreGlobals();
  181.  
  182.     return result;
  183. }
  184.  
  185. arHookResult Plugin::KeyEvent(Short /*theChar*/, Short /*key*/, Short /*modifiers*/)
  186. {
  187.     return false; // Let Arrange handle the event
  188. } // KeyEvent
  189.  
  190.  
  191. /* This function is called whenever the user chooses a menu item for which
  192.  * we have registered (via the SetMenuHook function).  It should return true
  193.  * if we handle the command, false (the normal case) when the command should
  194.  * be passed along to other plug-ins or to Arrange's normal event processing.
  195.  * See the documentation for SetMenuHook for more details.
  196.  */
  197. void Plugin::InstallMenuHook  ( uInteger refcon, pBoolean addHook, Integer commandCode )
  198. {
  199.     calls->ui->SetMenuHook (OurMenuHook, refcon, addHook, commandCode);
  200. }
  201.  
  202. arHookResult OurMenuHook( ModuleParamBlock* pb, Integer commandCode,
  203.                                     Integer commandParam, pShort modifiers ENDP )
  204. {
  205.     arHookResult    result;
  206.  
  207.     SetupGlobals();
  208.     result = ((SubClass*)(pb->moduleRefcon))->MenuEvent( 
  209.                     commandCode, commandParam, modifiers );
  210.     RestoreGlobals();
  211.     return result;
  212. }
  213.  
  214. arHookResult Plugin::MenuEvent( Integer /*commandCode*/, Integer /*commandParam*/,
  215.                                             Short /*modifiers*/ )
  216. {
  217.     return false; // Let Arrange handle the event
  218. } // MenuEvent
  219.  
  220.  
  221. /* If we register to recieve events for a field by calling SetFieldHook, this
  222.  * function will be called for any events in that field.  It should return
  223.  * false in almost all cases.  See the documentation for SetFieldHook for
  224.  * more details.
  225.  */
  226. void Plugin::InstallFieldHook ( uInteger refcon, pBoolean addHook, arFieldID field )
  227. {
  228.     calls->ui->SetFieldHook(OurFieldHook, refcon, addHook, field);
  229. }
  230.  
  231. void Plugin::RegisterFieldProc (const char* name, Integer id, arFPType type,
  232.                                 Integer fieldTypes, uInteger refcon ENDP )
  233. {
  234.     calls->ui->RegisterFieldProc( name, id, type, fieldTypes, OurFieldHook, refcon );
  235. }
  236.  
  237. arHookResult OurFieldHook( ModuleParamBlock* pb, arNoteID note,
  238.                              arFieldID field, arFieldAction action,
  239.                              const char* choiceText ENDP )
  240. {
  241.     arHookResult    result;
  242.  
  243.     SetupGlobals();
  244.     result = ((SubClass*)(pb->moduleRefcon))->FieldEvent(
  245.                             note, field, action,choiceText );
  246.     RestoreGlobals();
  247.     return result;
  248. }
  249.  
  250. arHookResult Plugin::FieldEvent( arNoteID /*note*/, arFieldID /*field*/,
  251.                                  arFieldAction /*action*/, const char* /*choiceText*/ )
  252. {
  253.     return false;
  254. } // FieldEvent
  255.  
  256.  
  257. /*    This function is called whenever the user switches windows or changes
  258.     the current folder/topic/view in the front window.  See the documentation
  259.     for SetTopicHook for more details.
  260. */
  261. void Plugin::InstallTopicHook ( uInteger refcon, pBoolean addHook )
  262. {
  263.     calls->ui->SetTopicHook(OurTopicHook, refcon, addHook);
  264. }
  265.  
  266. void OurTopicHook( ModuleParamBlock* pb, arTopicID newTopic,
  267.                              arWindowID newWindow, arTopicAction action ENDP )
  268. {
  269.     SetupGlobals();
  270.     ((SubClass*)(pb->moduleRefcon))->TopicEvent(newTopic, newWindow, action);
  271.     RestoreGlobals();
  272. }
  273.  
  274. void Plugin::TopicEvent( arTopicID /*newTopic*/, arWindowID /*newWindow*/,
  275.                                   arTopicAction /*action*/ )
  276. {
  277. } // TopicEvent
  278.  
  279.  
  280. /*    This function is called periodically, whenever Arrange recieves a null
  281.     event from the Event Manager.
  282. */
  283. void Plugin::InstallTickHook( uInteger refcon, pBoolean addHook )
  284. {
  285.     calls->ui->SetTickHook (OurTickHook, refcon, addHook);
  286. }
  287.  
  288. void OurTickHook(ModuleParamBlock* pb ENDP)
  289. {
  290.     SetupGlobals();
  291.     ((SubClass*)(pb->moduleRefcon))->TickEvent();
  292.     RestoreGlobals();
  293. }
  294.  
  295. void Plugin::TickEvent()
  296. {
  297. } // TickEvent
  298.  
  299.  
  300. /* This function is called whenever various file-level events occur.  It
  301.  * should return true in almost all cases.  See the documentation for
  302.  * SetFileHook for more details.
  303.  */
  304. void Plugin::InstallFileHook  ( uInteger refcon, pBoolean addHook )
  305. {
  306.     calls->ui->SetFileHook (OurFileHook, refcon, addHook);
  307. }
  308.  
  309. arHookResult OurFileHook(ModuleParamBlock* pb, arFileAction action ENDP)
  310. {
  311.     arHookResult result;
  312.  
  313.     SetupGlobals();
  314.     result = ((SubClass*)(pb->moduleRefcon))->FileEvent(action);
  315.     RestoreGlobals();
  316.     return result;
  317. }
  318.  
  319. arHookResult Plugin::FileEvent(arFileAction /*action*/)
  320. {
  321.     return true;
  322. } // FileEvent
  323.  
  324.  
  325. /* This function is called if the user voluntarily quits Arrange.  It should
  326.  * return true to allow the user to quit, false to prevent it.  See the
  327.  * documentation for SetQuitHook for more details.
  328.  */
  329. void Plugin::InstallQuitHook( uInteger refcon, pBoolean addHook )
  330. {
  331.     calls->ui->SetQuitHook(OurQuitHook, refcon, addHook);
  332. }
  333.  
  334. arHookResult OurQuitHook(ModuleParamBlock* pb ENDP)
  335. {
  336.     arHookResult result;
  337.  
  338.     SetupGlobals();
  339.     result = ((SubClass*)(pb->moduleRefcon))->QuitEvent();
  340.     RestoreGlobals();
  341.     return result;
  342. }
  343.  
  344. arHookResult Plugin::QuitEvent()
  345. {
  346.     return true;
  347. } // QuitEvent
  348.  
  349.  
  350. /* This function is called whenever the user clicks in the menu bar or types
  351.  * a command key, just before processing the event.  It should do any fixing
  352.  * up of menus which might be necessary based on the current state of affairs.
  353.  * See the documentation for SetATMHook for more details.
  354.  */
  355. void Plugin::InstallATMHook( uInteger refcon, pBoolean addHook )
  356. {
  357.     calls->ui->SetATMHook(OurATMHook, refcon, addHook);
  358. }
  359.  
  360. void OurATMHook(ModuleParamBlock* pb ENDP)
  361. {
  362.     SetupGlobals();
  363.     ((SubClass*)(pb->moduleRefcon))->ATMEvent();
  364.     RestoreGlobals();
  365. }
  366.  
  367. void Plugin::ATMEvent()
  368. {
  369. } // ATMEvent
  370.  
  371.  
  372. /***********************************************************************/
  373. /*
  374.     This function is called whenever the user imports a file of a type
  375.     for which this plugin registered a format. It is called first to
  376.     assess how likely it is that the provided format is the import
  377.     format supported, and then again to import the format.
  378. */
  379. void Plugin::RegisterImportFormat( const char* name, Integer formatID,
  380.                             OSType* fileTypes, Integer fileTypeCount,
  381.                             uInteger refcon ENDP )
  382. {
  383.     calls->ui->RegisterImportFormat( name, formatID, fileTypes, fileTypeCount,
  384.                                      OurImportHook, refcon );
  385. }
  386.  
  387. Integer OurImportHook( ModuleParamBlock* pb, const FSSpec *file,
  388.                           pShort fRefnum, Integer formatID,
  389.                           pBoolean sniff, arTopicID destTopic ENDP )
  390. {
  391.     Integer result;
  392.     SetupGlobals();
  393.     result = ((SubClass*)(pb->moduleRefcon))->ImportFile( file, fRefnum, formatID,
  394.                                                         sniff, destTopic );
  395.     RestoreGlobals();
  396.     return result;
  397. }
  398.  
  399. Integer Plugin::ImportFile( const FSSpec* /*file*/, pShort /*fRefnum*/,
  400.                             Integer /*formatID*/, pBoolean /*sniff*/, arTopicID /*destTopic*/ )
  401. {
  402.     return 0;
  403. }
  404.  
  405. /*
  406.     Export the provided topic to the given file. Assume that the file is already
  407.     open, and leave the file open and unflushed.
  408. */
  409. void Plugin::RegisterExportFormat ( const char* name, Integer formatID, arEFType type,
  410.                              uInteger refcon, OSType fileType, OSType fileCreator ENDP )
  411. {
  412.     calls->ui->RegisterExportFormat( name, formatID, type,
  413.                                         OurExportHook, refcon, fileType, fileCreator );
  414. }
  415.  
  416. Integer    OurExportHook( ModuleParamBlock* pb, const FSSpec *file,
  417.                        pShort fRefnum, Integer formatID,
  418.                        arEFType type, arTopicID srcTopic ENDP )
  419. {
  420.     Integer result;
  421.     SetupGlobals();
  422.     result = ((SubClass*)(pb->moduleRefcon))->ExportTopic(file, fRefnum, formatID, type, srcTopic);
  423.     RestoreGlobals();
  424.     return result;
  425. }
  426.  
  427. Integer Plugin::ExportTopic(const FSSpec* /*file*/,
  428.                             pShort /*fRefnum*/, Integer /*formatID*/,
  429.                             arEFType /*type*/, arTopicID /*srcTopic*/)
  430. {
  431.     return 0;
  432. }
  433.  
  434. /**************************************************************************************/
  435.  
  436.